<?php

/**
 * JingYao-backend
 *
 * @link     https://gitee.com/wang-zhihui-release/jingyao-backend
 * @apiDocument https://gitee.com/wang-zhihui-release/jingyao-backend/wikis/
 */

namespace App\Services;

use App\Enums\AdminActionTypeEnum;
use App\Enums\AdminCheckEnum;
use App\Enums\AdminSetHouserScoreEnum;
use App\Enums\CheckStatusEnum;
use App\Enums\UserIdentityEnum;
use App\Events\CheckSuccess;
use App\Exceptions\ApiException;
use App\Format\CheckSuccessFormat;
use App\Format\HouserScoreFormat;
use App\Models\House;
use App\Models\HouserScore;
use App\Models\HouserScoreResult;
use App\Models\HouseUserBind;
use App\Models\User;
use App\Models\UserProfile;
use Illuminate\Support\Facades\Log;

class HouserScoreService
{
    public function setScore(HouserScoreFormat $houserScoreFormat)
    {
        // 要检查这个 "房东" 有没有通过审核
        $houserId = $houserScoreFormat->getHouseId();
        /** @var House $houserModel */
        $houserModel = House::query()->select('houser_user_id')->find($houserId);
        /** @var User $houser */
        $houser = User::query()->select('identity')->find($houserModel->houser_user_id);
        if ($houser->identity != UserIdentityEnum::HOUSER) {
            Log::error('这个房屋不应该出现的', [
                'data' => $houserScoreFormat->toArray(),
            ]);
            throw new ApiException('此房屋不能评价', 1);
        }
        // 检查租户能不能打分
        /** @var UserProfile $liver */
        $liver = UserProfile::query()->select('id_card_number', 'identity')->where('user_id', $houserScoreFormat->getUserId())->first();
        if ($liver->identity != UserIdentityEnum::FLOW_USER) {
            throw new ApiException('非流动人口不能打分', 1);
        }
        $houseUserBind = HouseUserBind::query()
            ->where('house_id', $houserScoreFormat->getHouseId())
            ->where('id_card_number', $liver->id_card_number)->exists();
        if (! $houseUserBind) {
            throw new ApiException('不能给不是自己租住的房屋打分', 1);
        }
        $houserScoreFormat->setScoreTime(time());
        $check = HouserScore::query()
            ->where('user_id', $houserScoreFormat->getUserId())
            ->where('house_id', $houserScoreFormat->getHouseId())
            ->where('check_status', CheckStatusEnum::CHECK_ADOPT)
            ->exists();
        if ($check) {
            throw new ApiException('不能重复评分', 1);
        }
        $houserScoreFormat->setCheckStatus(CheckStatusEnum::CHECK_ING);
        if ($houserScoreFormat->getId()) {
            HouserScore::query()->where('id', $houserScoreFormat->getId())->update($houserScoreFormat->toArrayNotNull());
            return true;
        }
        $exists = HouserScore::query()
            ->where('house_id', $houserScoreFormat->getHouseId())
            ->where('user_id', $houserScoreFormat->getUserId())
            ->exists();
        if ($exists) {
            HouserScore::query()
                ->where('house_id', $houserScoreFormat->getHouseId())
                ->where('user_id', $houserScoreFormat->getUserId())
                ->update($houserScoreFormat->toArrayNotNull());
            return true;
        }
        HouserScore::query()->create($houserScoreFormat->toArrayNotNull());
        return true;
    }

    public function getMySetScore(int $userId, int $houseId)
    {
        $res = HouserScore::query()->with([
            'house',
            'house.houser:name,now_address,user_id',
        ])->where('user_id', $userId)->where('house_id', $houseId)->first();
        if (empty($res)) {
            return [];
        }
        return $res->toArray();
    }

    public function getMySetScoreList(int $userId, int $page, int $pageSize, array $search)
    {
        $builder = HouserScore::query()->where('user_id', $userId)->orderByDesc('score_time');

        if (isset($search['houser_name'])) {
            $houserIds = UserProfile::query()->where('name', 'like', '%' . $search['houser_name'] . '%')
                ->select('user_id')->pluck('user_id')->toArray();

            $myHouserIds = $this->findMyHistoryHouser($userId);
            $findHouserId = array_values(array_intersect($houserIds, $myHouserIds));
            if (empty($findHouserId)) {
                return [];
            }
            $findHouseIds = House::query()->whereIn('houser_user_id', $findHouserId)->select('id')
                ->pluck('id')->toArray();

            $builder->whereIn('house_id', $findHouseIds);
        }

        $count = $builder->count();
        $list = $builder->skip(($page - 1) * $pageSize)->take($pageSize)->get()->toArray();

        foreach ($list as &$value) {
            $value['houser_name'] = $this->findHouserNameFromHouseId($value['house_id']);
        }

        return [
            'page' => $page,
            'page_size' => $pageSize,
            'count' => $count,
            'list' => $list,
        ];
    }

    // 后台获取租客的评分列表
    public function getHouseScoreList(int $page, int $pageSize, array $search)
    {
        $builder = HouserScore::query()->with([
            'user:name,user_id',
            'house.houser:user_id,name',
        ]);
        if (isset($search['start_date'], $search['end_date'])) {
            $builder->where('score_time', '>=', strtotime($search['start_date']));
            if (strlen($search['end_date']) > 10) {
                $builder->where('score_time', '<=', strtotime($search['end_date']));
            } else {
                $builder->where('score_time', '<=', strtotime($search['end_date']) + (24 * 3600));
            }
        }
        if (isset($search['start_date']) && ! isset($search['end_date'])) {
            $builder->where('score_time', '>=', strtotime($search['start_date']));
        }
        if (! isset($search['start_date']) && isset($search['end_date'])) {
            if (strlen($search['end_date']) > 10) {
                $builder->where('score_time', '<=', strtotime($search['end_date']));
            } else {
                $builder->where('score_time', '<=', strtotime($search['end_date']) + (24 * 3600));
            }
        }
        if (isset($search['check_status'])) {
            $builder->where('check_status', $search['check_status']);
        }
        if (isset($search['houser_name'])) {
            $builder->whereHas('house.houser', function ($query) use ($search) {
                $query->where('name', 'like', '%' . $search['houser_name'] . '%');
            });
        }

        if (! empty($search)) {
            adminLog(new HouserScore(), AdminActionTypeEnum::SELECT, '查询评分');
        }

        $count = $builder->count();

        $list = $builder->skip(($page - 1) * $pageSize)->take($pageSize)->orderByDesc('id')->get();

        return [
            'page' => $page,
            'page_size' => $pageSize,
            'count' => $count,
            'list' => $list,
        ];
    }

    public function checkHouseScore(int $id, int $checkStatus, string $checkMessage)
    {
        /** @var null|HouserScore $houserSocer */
        $houserSocer = HouserScore::query()->find($id);
        if (empty($houserSocer)) {
            throw new ApiException('数据不存在', 1);
        }
        $houserSocer->check_status = $checkStatus;
        $houserSocer->check_message = $checkMessage;
        $houserSocer->save();
        event(new CheckSuccess(new CheckSuccessFormat([
            'check_status' => $checkStatus,
            'check_type' => AdminCheckEnum::CHECK_HOUSE_SCORE,
            'user_id' => $houserSocer->user_id,
        ])));
        return true;
    }

    public function calcScore()
    {
        $houerIds = User::query()->select('id')
            ->where('identity', UserIdentityEnum::HOUSER)
            ->get()->pluck('id')->toArray();

        foreach ($houerIds as $houerId) {
            $houserScore = $this->calcHouserScore($houerId);
            $result = HouserScoreResult::query()->where([
                'houser_id' => $houerId,
            ])->first();

            $adminSetScore = 0;
            $realScore = $houserScore;
            /** @var HouserScoreResult $houserScoreResult */
            $houserScoreResult = HouserScoreResult::query()->where('houser_id', $houerId)->first();
            if (! empty($houserScoreResult)) {
                if ($houserScoreResult->admin_config == AdminSetHouserScoreEnum::SETTED) {
                    $adminSetScore = $houserScoreResult->admin_set_score;
                    $realScore = $houserScoreResult->admin_set_score;
                }
            }

            if (empty($result)) {
                HouserScoreResult::query()->create([
                    'houser_id' => $houerId,
                    'houser_score' => $houserScore,
                    'admin_set_score' => $adminSetScore,
                    'real_score' => $realScore,
                ]);
            } else {
                $result->update([
                    'houser_score' => $houserScore,
                    'admin_set_score' => $adminSetScore,
                ]);
            }
            UserProfile::query()->where('user_id', $houerId)->update([
                'houser_score' => $realScore,
            ]);
        }
        return true;
    }

    public function adminSetHouserScore($houserId, $houserScore)
    {
        // 前期瞎 jb 设计
        // 搞得需求缺失
        // 房东的分数统计到 houser_score_result 表
        // 但是冗余在 profile 用来后台排序
        /** @var null|UserProfile $userProfile */
        $userProfile = UserProfile::query()->where('user_id', $houserId)
            ->select('houser_score', 'id')
            ->where('identity', UserIdentityEnum::HOUSER)->first();
        if (empty($userProfile)) {
            throw new ApiException('此用户不是房东', 1);
        }
        $userProfile->houser_score = $houserScore;
        $userProfile->save();

        $houserScoreResult = HouserScoreResult::query()->where([
            'houser_id' => $houserId,
        ])->first();
        if (empty($houserScoreResult)) {
            HouserScoreResult::query()->create([
                'houser_id' => $houserId,
                'houser_score' => $houserScore,
                'admin_set_score' => $houserScore,
                'real_score' => $houserScore,
                'admin_config' => AdminSetHouserScoreEnum::SETTED,
            ]);
        } else {
            $houserScoreResult->admin_set_score = $houserScore;
            $houserScoreResult->real_score = $houserScore;
            $houserScoreResult->admin_config = AdminSetHouserScoreEnum::SETTED;
            $houserScoreResult->save();
        }
        return true;
    }

    public function adminUnSetHouserScore($houserId)
    {
        /** @var HouserScoreResult $houserScoreResult */
        $houserScoreResult = HouserScoreResult::query()->where([
            'houser_id' => $houserId,
        ])->first();
        $calcHouserScore = $houserScoreResult->houser_score;
        UserProfile::query()->where('user_id', $houserId)->update([
            'houser_score' => $calcHouserScore,
        ]);

        $houserScoreResult->admin_config = AdminSetHouserScoreEnum::NOT_SET;
        $houserScoreResult->real_score = $calcHouserScore;
        $houserScoreResult->save();
        return true;
    }

    private function calcHouserScore(int $houserId)
    {
        // 找出这个房东下的所有房子
        $houses = House::query()->where('houser_user_id', $houserId)->get();
        if ($houses->count() == 0) {
            return 0;
        }
        // 计算每个房子的评分然后求平均值
        $score = 0;
        /** @var House $house */
        foreach ($houses as $house) {
            $score += $this->calcHouseScore($house->id);
        }
        return round($score / $houses->count(), 2);
    }

    // 按照一颗星1分，然后取所有星的平均分；
    // 3个评级环节一共15颗星，取平均分就是3个环节总评星
    // 当租赁模式为“合租”时，要取多人之和的平均值
    // 如果有历史租客的数据 取平均值
    private function calcHouseScore(int $houseId)
    {
        $scores = HouserScore::query()->where('house_id', $houseId)
            ->where('check_status', CheckStatusEnum::CHECK_ADOPT)
            ->get();
        if ($scores->count() == 0) {
            return 0;
        }
        // 这种计算方式兼容了合租和整租 都取平均值就是了 只不过整租的是除以 1
        $count = 0;
        /** @var HouserScore $score */
        foreach ($scores as $score) {
            $all = $score->environment_score + $score->synthetical_score + $score->service_score;
            $count += round($all / 3, 2);
        }
        return round($count / $scores->count(), 2);
    }

    // 获取我的历史房东们
    private function findMyHistoryHouser(int $userId)
    {
        $houseIds = HouserScore::query()->where('user_id', $userId)->select('house_id')
            ->pluck('house_id')->toArray();
        return House::query()->whereIn('id', $houseIds)->select('houser_user_id')
            ->pluck('houser_user_id')->toArray();
    }

    // 通过房子 ID 查询房东姓名
    private function findHouserNameFromHouseId(int $houseId)
    {
        /** @var House $houserId */
        $house = House::query()->where('id', $houseId)->select('houser_user_id')->first();
        /** @var null|UserProfile $user */
        $user = UserProfile::query()->where('user_id', $house->houser_user_id)->select('name')->first();
        if (empty($user)) {
            return '';
        }
        return $user->name;
    }
}
